import androidx.compose.runtime.mutableStateListOf
import com.malinskiy.adam.AndroidDebugBridgeClient
import com.malinskiy.adam.AndroidDebugBridgeClientFactory
import com.malinskiy.adam.interactor.StartAdbInteractor
import com.malinskiy.adam.request.device.Device
import com.malinskiy.adam.request.device.DeviceState
import com.malinskiy.adam.request.device.ListDevicesRequest
import com.malinskiy.adam.request.pkg.InstallRemotePackageRequest
import com.malinskiy.adam.request.sync.v1.PushFileRequest
import io.github.vinceglb.filekit.core.FileKit
import io.github.vinceglb.filekit.core.PickerMode
import io.github.vinceglb.filekit.core.PickerType
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import java.io.File

/**
 * zhulei 2024/7/30 10:56
 */
class MainVm {

    val apkList = mutableStateListOf<File>()
    val devices = mutableStateListOf<Device>()
    private lateinit var adb: AndroidDebugBridgeClient

    init {
        GlobalScope.launch {
            StartAdbInteractor().execute()
            adb = AndroidDebugBridgeClientFactory().build()
            // 连接的设备
            while (true) {
                delay(500L)
                val execute = adb.execute(ListDevicesRequest())
                // 不存在就加入
                execute.forEachIndexed { index, device ->
                    if (!devices.map { it.serial }.contains(device.serial)) {
                        devices.add(device)
                    }
                }
                // 没有就删除，有更新就更新
                devices.forEachIndexed { index, device ->
                    if (execute.map { it.serial }.contains(device.serial)) {
                        // 有变化才修改状态
                        execute.forEach {
                            if (it.serial == device.serial) {
                                if (it.state != device.state) {
                                    devices[index] = it
                                }
                            }
                        }
                    } else {
                        devices.removeAt(index)
                    }
                }
            }
        }
    }

    fun addApk(filePath: String) {
        apkList.add(File(filePath.replace("file:", "")))
    }

    fun selectApk() {
        // FileKit Core
        GlobalScope.launch {
            val result = FileKit.pickFile(
                type = PickerType.File(extensions = listOf("apk")),
                mode = PickerMode.Multiple(),
                title = "Pick Apk",
            )
            result?.forEach {
                it.file?.let { it1 -> apkList.add(it1) }
            }
        }
    }

    fun installApk() {
        /**
         * val apkFile = File("/my/precious/application/app-debug.apk")
         * val fileName = apkFile.name
         * val channel = adb.execute(PushFileRequest(testFile, "/data/local/tmp/$fileName"), GlobalScope, serial = device.serial)
         * while (!channel.isClosedForReceive) {
         *     val progress: Double? = channel.poll()
         * }
         * 执行请求后，我们需要轮询频道的进度，直到频道关闭。
         *
         * 接下来，我们需要实际安装此文件：
         *
         * val output: String = adb.execute(InstallRemotePackageRequest("/data/local/tmp/$fileName", true), serial = device.serial)
         * if(!output.startsWith("Success")) throw RuntimeException("Unable to install the apk")
         * 如果一切正常，则输出应包含类似 的内容。Success
         *
         * 接下来，我们可以验证此包是否确实已安装：
         *
         * val packages: List<Package> = adb.execute(PmListRequest(), serial = device.serial)
         * val pkg: Package? = packages.find { it.name == "com.example" }
         */
        println("start install apk")
        GlobalScope.launch {
            apkList.forEach { apkFile ->
                devices.forEach { device ->
                    if (device.state != DeviceState.OFFLINE) {
                        println("安装 $apkFile ${device.serial}")
                        val channel = adb.execute(
                            PushFileRequest(apkFile, "/data/local/tmp/${apkFile.name}"),
                            GlobalScope,
                            serial = device.serial
                        )
                        while (!channel.isClosedForReceive) {
                            channel.tryReceive().getOrNull()?.let { progress ->
                                println("progress $progress")
                            }
                        }
                        val output = adb.execute(
                            InstallRemotePackageRequest(
                                "/data/local/tmp/${apkFile.name}",
                                true
                            ), serial = device.serial
                        )
                        println("output ${output.output}")
                    }
                }

            }
        }
    }

}